﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using static System.Drawing.Image;

using ORM;
using static Constants;
using static Common;

public partial class Global : HttpApplication
{
	DbOperation DbOp = new SqlOperation(ConnStr);

	protected void Application_Start(object sender, EventArgs e)
	{
		new Task(() =>
		{
			while(true)
			{
				Thread.Sleep(100000);

				//删除无用文件（中止上传时会产生保存了磁盘但未录入数据库的文件）

				foreach (var key in Uploadings.Keys)
					if (DateTime.Now.Subtract(Uploadings[key]).TotalHours > 3)
						Uploadings.TryRemove(key, out var _);

				var dirs = Directory.GetDirectories(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "attachment"));
				var files = dirs.SelectMany(dir => Directory.GetFiles(dir)).Select(file => "/" + file.Split('\\').Reverse().Take(3).Reverse().JoinBy("/"));
				var junks = files.Except(Uploadings.Keys).Except(DbOp.Photo.GetByFVs().Select(photo => photo.Path_Val));
				foreach (var junk in junks) try { File.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, junk.Substring(1))); } catch { }
			}
		}, TaskCreationOptions.LongRunning).Start();
	}

	protected void Application_BeginRequest(object _, EventArgs __)
	{
		if (Request.Url.LocalPath == "/")
		{
			Response.Redirect($"/web/{(Request.Browser.IsMobileDevice ? "mlist.htm" : "list.htm")}");
			return;
		}

		switch (Enum.Parse(ThumbQ.List.GetType(), Request.QueryString["thumb"] ?? "None"))
		{
			case ThumbQ.List:
				thumb(ThumbQ.List);
				break;

			case ThumbQ.Detail:
				thumb(ThumbQ.Detail);
				break;
		}
	}

	void thumb(ThumbQ quality)
	{
		var path = Server.MapPath(Request.Url.LocalPath);
		var thb = path.Replace(@"\attachment\", @"\thumb\");
		if (quality == ThumbQ.List && File.Exists(thb))
		{
			Response.TransmitFile(thb);
			Response.End();
			return;
		}

		var image = Image.FromFile(path);
		var wtf = new GetThumbnailImageAbort(() => false);

		var rotate = image.PropertyItems.SingleOrDefault(p => p.Id == 0x112)?.Value[0];
		var (width, height) = rotate == 6 || rotate == 8 ? (image.Height, image.Width) : (image.Width, image.Height);

		switch (quality)
		{
			case ThumbQ.List:
				{
					if (width <= 500 || height <= 500)      //比需要的尺寸大不了多少就直接用原图让客户端缩放
					{
						image.Dispose();
						return;
					}

					var ratio = 300m / Math.Min(width, height);
					var img = image.GetThumbnailImage(Convert.ToInt32(ratio * width), Convert.ToInt32(ratio * height), wtf, IntPtr.Zero);
					image.Dispose();
					image = img;
					if (width > 300)
						Graphics.FromImage(new Bitmap(300, height)).DrawImage(image, (width - 300) / 2, 0, 300, height);
					else if (height > 300)
						Graphics.FromImage(new Bitmap(width, 300)).DrawImage(image, 0, (height - 300) / 2, width, 300);
				}
				break;

			case ThumbQ.Detail:
				{
					if (width <= 1500)                      //比需要的尺寸大不了多少就直接用原图让客户端缩放
					{
						image.Dispose();
						return;
					}

					var ratio = 1200m / width;
					height = Convert.ToInt32(ratio * height);
					reduceImage(ref image, 1200, height);
				}
				break;
		}

		var ext = new FileInfo(path).Extension.ToLower().Replace(".", "");
		var format = ext switch { "bmp" => ImageFormat.Bmp, "png" => ImageFormat.Png, "gif" => ImageFormat.Gif, "ico" => ImageFormat.Icon, "tiff" => ImageFormat.Tiff, "wmf" => ImageFormat.Wmf, "exif" => ImageFormat.Exif, _ => ImageFormat.Jpeg };
		var response = HttpContext.Current.Response;
		response.ContentType = "image/" + ext;
		image.Save(response.OutputStream, format);
		if (quality == ThumbQ.List)
		{
			Directory.CreateDirectory(new FileInfo(thb).DirectoryName);
			image.Save(thb, format);
		}
		image.Dispose();
		response.End();
	}

	void reduceImage(ref Image img, int width, int height)
	{
		var bmp = new Bitmap(width, height, img.PixelFormat);
		bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution);

		using (var g = Graphics.FromImage(bmp))
		{
			g.Clear(Color.Transparent);
			g.InterpolationMode = InterpolationMode.Low;
			g.SmoothingMode = SmoothingMode.AntiAlias;
			g.DrawImage(img, new Rectangle(0, 0, width, height), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
		}

		img.Dispose();
		img = bmp;
	}
}